package com.logic.modular.game.building.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.comment.exception.ServiceException;
import com.logic.comment.util.XSThreadUtil;
import com.logic.modular.game.battle.info.base.PvpPlayerInfo;
import com.logic.modular.game.battle.info.base.PvpPlayerInfoServiceImpl;
import com.logic.modular.game.building.domain.PvpCityBuildings;
import com.logic.modular.game.building.mapper.PvpCityBuildMapper;
import com.logic.modular.game.player.bag.service.BagItemServiceImpl;
import com.logic.modular.game.player.bag.service.PlayerPropType1ServiceImpl;
import com.logic.modular.game.player.bag.service.PlayerPropType2ServiceImpl;
import com.logic.modular.game.player.info.service.PlayerStatusServiceImpl;
import com.logic.modular.game.PvpCity;
import com.logic.modular.game.player.match.service.PvpCityServiceImpl;
import com.comment.pojo.domain.logic.core.CoreCityBuildings;
import com.logic.modular.gameCore.map.service.CoreCityBuildingsServiceImpl;
import com.logic.modular.gameCore.map.service.CoreCityServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.logic.modular.game.core.service.MatchTaskServiceImpl.SURVIVAL_MATCH_IDS;
import static com.logic.modular.game.core.service.MatchTaskServiceImpl.survivalMatchIds;


/**
 * 城池信息(PvpCity)表服务实现类
 *
 * @author cxy
 * @since 2024-07-22 15:13:38
 */
@Slf4j
@Service
public class PvpCityBuildServiceImpl extends PvpCityBuildMapper {
    @Resource
    private CoreCityServiceImpl coreCityServiceImpl;
    @Resource
    private PvpCityServiceImpl pvpCityService;
    @Resource
    private CoreCityBuildingsServiceImpl coreCityBuildingsServiceImpl;
    @Resource
    private PlayerStatusServiceImpl playerMatchServiceImpl;
    @Resource
    private PvpPlayerInfoServiceImpl pvpPlayerInfoServiceImpl;
    @Resource
    private PlayerPropType1ServiceImpl playerPropType1Service;
    @Resource
    private XSThreadUtil xsThreadUtil;
    @Resource
    private BagItemServiceImpl bagItemServiceImpl;
    @Resource
    private PlayerPropType2ServiceImpl playerPropType2ServiceImpl;

    /**
     * 获取玩家当前对局所有城池建筑
     */
    public Map<Long, Map<String, PvpCityBuildings>> map(Long playerId) {
        Long currentMatchId = playerMatchServiceImpl.currentMatchId(playerId);
        List<PvpCityBuildings> pvpCityBuildings =
                listCache(currentMatchId).stream().filter(item -> Objects.equals(item.getPlayerId(), playerId)).collect(Collectors.toList());
        Map<Long, Map<String, PvpCityBuildings>> map = new HashMap<>();
        pvpCityBuildings.forEach(item -> {
            Map<String, PvpCityBuildings> map1 = map.computeIfAbsent(item.getCoreCityId(), k -> new HashMap<>());
            map1.put(item.getNo().toString(), item);
            map.put(item.getCoreCityId(), map1);
        });
        return map;
    }


    public PvpCityBuildings build(
            Long playerId,
            Long targetCityId, // 城池id
            Integer cityBuildNo,// 地块编号
            Long coreCityBuildingId// 建筑编号
    ) {

        // 获取账户
        Long currentMatchId = playerMatchServiceImpl.currentMatchId(playerId);

        PvpPlayerInfo pvpPlayerInfo = pvpPlayerInfoServiceImpl.get(currentMatchId, playerId);
        Set<Long> currentCity = pvpPlayerInfo.getCurrentCity();
        if (!currentCity.contains(targetCityId)) {
            throw new ServiceException("当前城池不属于你");
        }

        if (pvpPlayerInfo.getIsExit() == 1) {
            throw new ServiceException("你已退出对局");
        }

        CoreCityBuildings coreCityBuilding = coreCityBuildingsServiceImpl.getCache(coreCityBuildingId);
        if (coreCityBuilding.getLevel() > 1) {
            throw new ServiceException("请先建筑1级建筑");
        }

        Long levelUpTime = coreCityBuilding.getLevelUpTime();
        Long levelUpCost = coreCityBuilding.getLevelUpCost();

        Integer landNum = CoreCityServiceImpl.getCache(targetCityId).getLandNum();
        int size = (int) listCache(currentMatchId).stream().filter(item -> com.logic.comment.util.BeanUtil.selector()
                .bool(item.getStatus() != 0)
                .eq(targetCityId, item.getCoreCityId())
                .value()).count();
        if (size >= landNum) {
            throw new ServiceException("城池内建筑数量已达上限");
        }
        boolean b = playerPropType1Service.tryPay(playerId, 4L, BigDecimal.valueOf(levelUpCost));
        PvpCityBuildings pvpCityBuildings = new PvpCityBuildings();
        if (b) {
            log.info("开始建造,{}-{}-{}-{}", playerId, targetCityId, cityBuildNo, coreCityBuildingId);
            pvpCityBuildings.init(playerId, targetCityId, cityBuildNo, currentMatchId);
            pvpCityBuildings.building(coreCityBuildingId, levelUpTime, coreCityBuilding);
            saveCache(pvpCityBuildings);
        }
        return pvpCityBuildings;
    }

    public PvpCityBuildings buildUp(Long playerId, Long targetCityId, Integer no) {
        // 获取账户
        Long currentMatchId = playerMatchServiceImpl.currentMatchId(playerId);
        PvpCityBuildings pvpCityBuildings = selectCache(playerId, currentMatchId, targetCityId, no);

        if (pvpCityBuildings == null) {
            throw new ServiceException("当前建造不可操作");
        }
        if (pvpCityBuildings.getStatus() != 1) {
            tryBuilding(pvpCityBuildings);
            if (pvpCityBuildings.getStatus() != 1) {
                throw new ServiceException("当前建造不可操作");
            }
        }

        Long coreCityBuildingId = pvpCityBuildings.getCorePvpCityBuildingId();
        CoreCityBuildings up = coreCityBuildingsServiceImpl.getCache(coreCityBuildingId + 1);
        boolean equals = pvpCityBuildings.getType().equals(up.getType());
        if (!equals) {
            throw new ServiceException("升级条件不满足");
        }

        Long levelUpCost = up.getLevelUpCost();// 铜币
        boolean b = playerPropType1Service.tryPay(playerId, 4L, BigDecimal.valueOf(levelUpCost));
        if (!b) {
            throw new ServiceException("铜币不足");
        } else {
            log.info("开始升级建筑,{}-{}-{}", playerId, targetCityId, no);
            pvpCityBuildings.setCorePvpCityBuildingId(up.getId());
            pvpCityBuildings.setPlayerId(playerId);
            pvpCityBuildings.setStatus(2);
            pvpCityBuildings.setLevel(up.getLevel());
            pvpCityBuildings.setFinishTime(DateUtil.offsetSecond(new Date(), up.getLevelUpTime().intValue()).getTime());
            saveCache(pvpCityBuildings);
        }
        return pvpCityBuildings;
    }

    public void remove(Long playerId, Long targetCityId, Integer no) {
        // 获取账户
        Long currentMatchId = playerMatchServiceImpl.currentMatchId(playerId);
        PvpCityBuildings pvpCityBuildings = selectCache(playerId, currentMatchId, targetCityId, no);
        if (pvpCityBuildings == null) {
            throw new ServiceException("建筑不存在");
        }
        if (pvpCityBuildings.getCorePvpCityBuildingId() == null) {
            throw new ServiceException("当前地块不存在建筑");
        }
        if (pvpCityBuildings.getStatus() != 1) {
            throw new ServiceException("当前建造不可操作");
        }
        Long corePvpCityBuildingId = pvpCityBuildings.getCorePvpCityBuildingId();
        pvpCityBuildings.clear();
        saveCache(pvpCityBuildings);
        /////////////////// 减少城市内政以及产力值
        CoreCityBuildings cache = coreCityBuildingsServiceImpl.getCache(corePvpCityBuildingId);
        PvpCity pvpCity = pvpCityService.getPlayerCity(playerId, targetCityId, currentMatchId);
        pvpCity.setGrainRate(pvpCity.getGrainRate() - cache.getGrainRate());
        pvpCity.setCopperRate(pvpCity.getCopperRate() - cache.getCopperRate());
        pvpCity.setReadyArmyRate(pvpCity.getReadyArmyRate() - cache.getReadyArmyRate());
        pvpCityService.update(pvpCity);
    }



    /**
     * 使用 内政建筑道具-2005L-能人巧匠-立刻完成建造
     */
    public PvpCityBuildings userProp2005(
            Long playerId, Long targetCityId, String no
    ) {
        Map<Long, Map<String, PvpCityBuildings>> map = map(playerId);
        PvpCityBuildings pvpCityBuildings = map.get(targetCityId).get(no);
        if (pvpCityBuildings == null) {
            throw new ServiceException("建筑不存在,请先建造");
        }
        Integer status = pvpCityBuildings.getStatus();
        if (status == 1) {
            throw new ServiceException("未建造状态无法加速");
        }
        if (status == 2) {
            BigDecimal userValue = BigDecimal.valueOf(1);
            boolean b = playerPropType2ServiceImpl.tryPayProp(playerId, 2005L, userValue);
            if (b) {
                try {
                    pvpCityBuildings.setFinishTime(new Date().getTime());
                    saveCache(pvpCityBuildings);
                } catch (Exception e) {
                    // 回滚道具
                    bagItemServiceImpl.obtainBagItem(playerId, 2005L, userValue);
                    throw new ServiceException("加速失败");
                }
            } else {
                throw new ServiceException("加速道具不足");
            }
        }
        return pvpCityBuildings;
    }

    @PostConstruct
    public void buildingHeart() {
        xsThreadUtil.scheduledExecutorService().scheduleAtFixedRate(this::buildingTask, 500, 1000, TimeUnit.MILLISECONDS);
    }

    private void buildingTask() {
        try {
            Set<Long> matchIds = survivalMatchIds.get(SURVIVAL_MATCH_IDS);
            if (matchIds != null) {
                matchIds.forEach(matchId -> listCache(matchId).forEach(this::tryBuilding));
            }
        } catch (Exception e) {
            // 异常处理
            log.error("buildingTask failed", e);
        }
    }

    private void tryBuilding(PvpCityBuildings item) {
        Integer status = item.getStatus();
        //  建造任务
        if (status == 2) {
            Long finishTime = item.getFinishTime();
            long thisTime = new Date().getTime();
            if (thisTime >= finishTime) {
                item.setStatus(1);
                saveCache(item);

                // // 增加城池的生产力
                CoreCityBuildings cache = coreCityBuildingsServiceImpl.getCache(item.getCorePvpCityBuildingId());
                PvpCity pvpCity = pvpCityService.getPlayerCity(item.getPlayerId(), item.getCoreCityId(), item.getMatchId());

                Map<String, Object> source = BeanUtil.beanToMap(pvpCity, "readyArmyRate", "copperRate", "grainRate");

                Long sourceGrainRate = pvpCity.getGrainRate();
                Long growUpGrainRate = cache.getGrainRate();
                if (growUpGrainRate > 0L) {
                    long targetGrainRate = sourceGrainRate + growUpGrainRate;
                    pvpCity.setGrainRate(targetGrainRate);
                }

                Long sourceCopperRate = pvpCity.getCopperRate();
                Long growUpCopperRate = cache.getCopperRate();
                if (growUpCopperRate > 0L) {
                    long targetCopperRate = sourceCopperRate + growUpCopperRate;
                    pvpCity.setCopperRate(targetCopperRate);
                }

                Long sourceReadyArmyRate = pvpCity.getReadyArmyRate();
                Long growUpReadyArmyRate = cache.getReadyArmyRate();
                if (growUpReadyArmyRate > 0L) {
                    long targetReadyArmyRate = sourceReadyArmyRate + growUpReadyArmyRate;
                    pvpCity.setReadyArmyRate(targetReadyArmyRate);
                }

                Map<String, Object> target = BeanUtil.beanToMap(pvpCity, "readyArmyRate", "copperRate", "grainRate");
                log.info("{},建造成功", item);
                log.info("{}-{}-{}, 建造前{}", pvpCity.getMatchId(), pvpCity.getOwnerUid(), pvpCity.getCoreCityId(), source);
                log.info("{}-{}-{}, 建造后{}", pvpCity.getMatchId(), pvpCity.getOwnerUid(), pvpCity.getCoreCityId(), target);

                pvpCityService.update(pvpCity);
            }
        }
    }
}